home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 5 / Gekikoh Dennoh Club Vol. 5 (Japan).7z / Gekikoh Dennoh Club Vol. 5 (Japan) (Track 01).bin / internet / xip / iijppp.lzh / src / ipcp.c < prev    next >
C/C++ Source or Header  |  1994-10-23  |  11KB  |  458 lines

  1. /*
  2.  *    PPP IP Control Protocol (IPCP) Module
  3.  *
  4.  *        Written by Toshiharu OHNO (tony-o@iij.ad.jp)
  5.  *
  6.  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that the above copyright notice and this paragraph are
  10.  * duplicated in all such forms and that any documentation,
  11.  * advertising materials, and other materials related to such
  12.  * distribution and use acknowledge that the software was developed
  13.  * by the Internet Initiative Japan, Inc.  The name of the
  14.  * IIJ may not be used to endorse or promote products derived
  15.  * from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  *
  20.  *    TODO:
  21.  *        o More RFC1772 backwoard compatibility
  22.  */
  23. #include "fsm.h"
  24. #include "lcpproto.h"
  25. #include "lcp.h"
  26. #include "ipcp.h"
  27. #include <netdb.h>
  28. #include <netinet/in_systm.h>
  29. #include <netinet/ip.h>
  30. #include <arpa/inet.h>
  31. #include <sys/socket.h>
  32. #include "slcompress.h"
  33. #include "os.h"
  34. #include "phase.h"
  35. #include "vars.h"
  36.  
  37. extern void PutConfValue();
  38. extern void Prompt();
  39. extern struct in_addr ifnetmask;
  40.  
  41. struct ipcpstate IpcpInfo;
  42. struct in_range DefMyAddress, DefHisAddress;
  43.  
  44. static void IpcpSendConfigReq(struct fsm *);
  45. static void IpcpSendTerminateAck(struct fsm *);
  46. static void IpcpSendTerminateReq(struct fsm *);
  47. static void IpcpDecodeConfig();
  48. static void IpcpLayerStart(struct fsm *);
  49. static void IpcpLayerFinish(struct fsm *);
  50. static void IpcpLayerUp(struct fsm *);
  51. static void IpcpLayerDown(struct fsm *);
  52. static void IpcpInitRestartCounter(struct fsm *);
  53.  
  54. static struct pppTimer IpcpReportTimer;
  55.  
  56. static int lastInOctets, lastOutOctets;
  57.  
  58. #define    REJECTED(p, x)    (p->his_reject & (1<<x))
  59.  
  60. struct fsm IpcpFsm = {
  61.   "IPCP",
  62.   PROTO_IPCP,
  63.   IPCP_MAXCODE,
  64.   OPEN_ACTIVE,
  65.   ST_INITIAL,
  66.   0, 0, 0,
  67.  
  68.   0,
  69.   { 0, 0, 0, NULL, NULL, NULL },
  70.  
  71.   IpcpLayerUp,
  72.   IpcpLayerDown,
  73.   IpcpLayerStart,
  74.   IpcpLayerFinish,
  75.   IpcpInitRestartCounter,
  76.   IpcpSendConfigReq,
  77.   IpcpSendTerminateReq,
  78.   IpcpSendTerminateAck,
  79.   IpcpDecodeConfig,
  80. };
  81.  
  82. static char *cftypes[] = {
  83.   "???", "IPADDRS", "COMPPROTO", "IPADDR",
  84. };
  85.  
  86. /*
  87.  * Function called every second. Updates connection period and idle period,
  88.  * also update LQR information.
  89.  */
  90. static void
  91. IpcpReportFunc()
  92. {
  93.   ipConnectSecs++;
  94.   if (lastInOctets == ipInOctets && lastOutOctets == ipOutOctets)
  95.     ipIdleSecs++;
  96.   lastInOctets = ipInOctets;
  97.   lastOutOctets = ipOutOctets;
  98.   StopTimer(&IpcpReportTimer);
  99.   IpcpReportTimer.state = TIMER_STOPPED;
  100.   StartTimer(&IpcpReportTimer);
  101. }
  102.  
  103. static void
  104. IpcpStartReport()
  105. {
  106.   ipIdleSecs = ipConnectSecs = 0;
  107.   StopTimer(&IpcpReportTimer);
  108.   IpcpReportTimer.state = TIMER_STOPPED;
  109.   IpcpReportTimer.load = SECTICKS;
  110.   IpcpReportTimer.func = IpcpReportFunc;
  111.   StartTimer(&IpcpReportTimer);
  112. }
  113.  
  114. void
  115. ReportIpcpStatus()
  116. {
  117.   struct ipcpstate *icp = &IpcpInfo;
  118.   struct fsm *fp = &IpcpFsm;
  119.  
  120.   printf("%s [%s]\n", fp->name, StateNames[fp->state]);
  121.   printf(" his side: %s, %x\n",
  122.      inet_ntoa(icp->his_ipaddr), icp->his_compproto);
  123.   printf(" my  side: %s, %x\n",
  124.      inet_ntoa(icp->want_ipaddr), icp->want_compproto);
  125.   printf("connected: %d secs, idle: %d secs\n\n", ipConnectSecs, ipIdleSecs);
  126.   printf("Defaults:  My Address: %s/%d  ",
  127.      inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width);
  128.   printf("His Address: %s/%d\n",
  129.      inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width);
  130. }
  131.  
  132. void
  133. IpcpDefAddress()
  134. {
  135.   struct hostent *hp;
  136.   char name[200];
  137.  
  138.   bzero(&DefMyAddress, sizeof(DefMyAddress));
  139.   bzero(&DefHisAddress, sizeof(DefHisAddress));
  140.   if (gethostname(name, sizeof(name)) == 0) {
  141.       hp = gethostbyname(name);
  142.       if (hp && hp->h_addrtype == AF_INET) {
  143.     bcopy(hp->h_addr, (char *)&DefMyAddress.ipaddr.s_addr, hp->h_length);
  144.       }
  145.   }
  146. }
  147.  
  148. void
  149. IpcpInit()
  150. {
  151.   struct ipcpstate *icp = &IpcpInfo;
  152.  
  153.   FsmInit(&IpcpFsm);
  154.   bzero(icp, sizeof(struct ipcpstate));
  155.   if ((mode & MODE_DEDICATED) && !dstsystem) {
  156.     icp->want_ipaddr.s_addr = icp->his_ipaddr.s_addr = 0;
  157.   } else {
  158.     icp->want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
  159.     icp->his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
  160.   }
  161.   if (icp->want_ipaddr.s_addr == 0)
  162.     icp->want_ipaddr.s_addr = htonl(0xc0000001);
  163.   if (Enabled(ConfVjcomp))
  164.     icp->want_compproto = (PROTO_VJCOMP << 16) | ((MAX_STATES - 1) << 8);
  165.   else
  166.     icp->want_compproto = 0;
  167.   icp->heis1172 = 0;
  168.   IpcpFsm.maxconfig = 10;
  169. }
  170.  
  171. static void
  172. IpcpInitRestartCounter(fp)
  173. struct fsm *fp;
  174. {
  175.   fp->FsmTimer.load = 3 * SECTICKS;
  176.   fp->restart = 5;
  177. }
  178.  
  179. static void
  180. IpcpSendConfigReq(fp)
  181. struct fsm *fp;
  182. {
  183.   u_char *cp;
  184.   struct ipcpstate *icp = &IpcpInfo;
  185.  
  186.   cp = ReqBuff;
  187.   LogPrintf(LOG_LCP, "%s: SendConfigReq\n", fp->name);
  188.   PutConfValue(&cp, cftypes, TY_IPADDR, 6, ntohl(icp->want_ipaddr.s_addr));
  189.   if (icp->want_compproto && !REJECTED(icp, TY_COMPPROTO)) {
  190.     if (icp->heis1172)
  191.       PutConfValue(&cp, cftypes, TY_COMPPROTO, 4, icp->want_compproto >> 16);
  192.     else
  193.       PutConfValue(&cp, cftypes, TY_COMPPROTO, 6, icp->want_compproto);
  194.   }
  195.   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
  196. }
  197.  
  198. static void
  199. IpcpSendTerminateReq(fp)
  200. struct fsm *fp;
  201. {
  202.   /* XXX: No code yet */
  203. }
  204.  
  205. static void
  206. IpcpSendTerminateAck(fp)
  207. struct fsm *fp;
  208. {
  209.   LogPrintf(LOG_LCP, "  %s: SendTerminateAck\n", fp->name);
  210.   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
  211. }
  212.  
  213. static void
  214. IpcpLayerStart(fp)
  215. struct fsm *fp;
  216. {
  217.   LogPrintf(LOG_LCP, "%s: LayerStart.\n", fp->name);
  218. }
  219.  
  220. static void
  221. IpcpLayerFinish(fp)
  222. struct fsm *fp;
  223. {
  224.   LogPrintf(LOG_LCP, "%s: LayerFinish.\n", fp->name);
  225.   LcpClose();
  226.   NewPhase(PHASE_TERMINATE);
  227. }
  228.  
  229. static void
  230. IpcpLayerDown(fp)
  231. struct fsm *fp;
  232. {
  233.   LogPrintf(LOG_LCP, "%s: LayerDown.\n", fp->name);
  234.   StopTimer(&IpcpReportTimer);
  235. }
  236.  
  237. /*
  238.  *  Called when IPCP has reached to OPEN state
  239.  */
  240. static void
  241. IpcpLayerUp(fp)
  242. struct fsm *fp;
  243. {
  244.   char tbuff[100];
  245.  
  246. #ifdef VERBOSE
  247.   fprintf(stderr, "%s: LayerUp(%d).\r\n", fp->name, fp->state);
  248. #endif
  249.   Prompt(1);
  250.   LogPrintf(LOG_LCP, "%s: LayerUp.\n", fp->name);
  251.   sprintf(tbuff, "myaddr = %s ", inet_ntoa(IpcpInfo.want_ipaddr));
  252.   LogPrintf(LOG_LCP, " %s hisaddr = %s\n", tbuff, inet_ntoa(IpcpInfo.his_ipaddr));
  253.   OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask);
  254.   OsLinkup();
  255.   IpcpStartReport();
  256.   StartIdleTimer();
  257. }
  258.  
  259. void
  260. IpcpUp()
  261. {
  262.   FsmUp(&IpcpFsm);
  263.   LogPrintf(LOG_LCP, "IPCP Up event!!\n");
  264. }
  265.  
  266. void
  267. IpcpOpen()
  268. {
  269.   FsmOpen(&IpcpFsm);
  270. }
  271.  
  272. static int
  273. AcceptableAddr(prange, ipaddr)
  274. struct in_range *prange;
  275. struct in_addr ipaddr;
  276. {
  277. #ifdef DEBUG
  278.   logprintf("requested = %x ", htonl(ipaddr.s_addr));
  279.   logprintf("range = %x", htonl(prange->ipaddr.s_addr));
  280.   logprintf("/%x\n", htonl(prange->mask.s_addr));
  281.   logprintf("%x, %x\n", htonl(prange->ipaddr.s_addr & prange->mask.s_addr),
  282.     htonl(ipaddr.s_addr & prange->mask.s_addr));
  283. #endif
  284.   return((prange->ipaddr.s_addr & prange->mask.s_addr) ==
  285.     (ipaddr.s_addr & prange->mask.s_addr));
  286. }
  287.  
  288. static void
  289. IpcpDecodeConfig(bp, mode)
  290. struct mbuf *bp;
  291. int mode;
  292. {
  293.   u_char *cp;
  294.   int plen, type, length;
  295.   u_long *lp, compproto;
  296.   struct compreq *pcomp;
  297.   struct in_addr ipaddr, dstipaddr;
  298.   char tbuff[100];
  299.  
  300.   plen = plength(bp);
  301.  
  302.   cp = MBUF_CTOP(bp);
  303.   ackp = AckBuff;
  304.   nakp = NakBuff;
  305.   rejp = RejBuff;
  306.  
  307.   while (plen >= sizeof(struct fsmconfig)) {
  308.     if (plen < 0)
  309.       break;
  310.     type = *cp;
  311.     length = cp[1];
  312.     if (type <= TY_IPADDR)
  313.       sprintf(tbuff, " %s[%d] ", cftypes[type], length);
  314.     else
  315.       sprintf(tbuff, " ");
  316.  
  317.     switch (type) {
  318.     case TY_IPADDR:        /* RFC1332 */
  319.       lp = (u_long *)(cp + 2);
  320.       ipaddr.s_addr = *lp;
  321.       LogPrintf(LOG_LCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
  322.  
  323.       switch (mode) {
  324.       case MODE_REQ:
  325.     if (!AcceptableAddr(&DefHisAddress, ipaddr)) {
  326.           /*
  327.            * If destination address is not acceptable, insist to use
  328.            * what we want to use.
  329.            */
  330.       bcopy(cp, nakp, 2);
  331.           bcopy(&IpcpInfo.his_ipaddr.s_addr, nakp+2, length);
  332.           nakp += length;
  333.           break;
  334.       
  335.     }
  336.     IpcpInfo.his_ipaddr = ipaddr;
  337.     bcopy(cp, ackp, length);
  338.     ackp += length;
  339.     break;
  340.       case MODE_NAK:
  341.     if (AcceptableAddr(&DefMyAddress, ipaddr)) {
  342.           /*
  343.            * Use address suggested by peer.
  344.            */
  345.       sprintf(tbuff+50, "%s changing address: %s ", tbuff, inet_ntoa(IpcpInfo.want_ipaddr));
  346.       LogPrintf(LOG_LCP, "%s --> %s\n", tbuff+50, inet_ntoa(ipaddr));
  347.       IpcpInfo.want_ipaddr = ipaddr;
  348.     }
  349.     break;
  350.       case MODE_REJ:
  351.     IpcpInfo.his_reject |= (1 << type);
  352.     break;
  353.       }
  354.       break;
  355.     case TY_COMPPROTO:
  356.       lp = (u_long *)(cp + 2);
  357.       compproto = htonl(*lp);
  358.       LogPrintf(LOG_LCP, "%s %08x\n", tbuff, compproto);
  359.  
  360.       switch (mode) {
  361.       case MODE_REQ:
  362.     if (!Acceptable(ConfVjcomp)) {
  363.       bcopy(cp, rejp, length);
  364.       rejp += length;
  365.     } else {
  366.       pcomp = (struct compreq *)(cp + 2);
  367.       switch (length) {
  368.       case 4:    /* RFC1172 */
  369.         if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
  370.           logprintf("** Peer is speaking RFC1172 compression protocol **\n");
  371.           IpcpInfo.heis1172 = 1;
  372.           IpcpInfo.his_compproto = compproto;
  373.           bcopy(cp, ackp, length);
  374.           ackp += length;
  375.         } else {
  376.           bcopy(cp, nakp, 2);
  377.           pcomp->proto = htons(PROTO_VJCOMP);
  378.           bcopy(&pcomp, nakp + 2, 2);
  379.           nakp += length;
  380.         }
  381.         break;
  382.       case 6:     /* RFC1332 */
  383.         if (ntohs(pcomp->proto) == PROTO_VJCOMP
  384.             && pcomp->slots < MAX_STATES && pcomp->slots > 2) {
  385.           IpcpInfo.his_compproto = compproto;
  386.           IpcpInfo.heis1172 = 0;
  387.           bcopy(cp, ackp, length);
  388.           ackp += length;
  389.         } else {
  390.           bcopy(cp, nakp, 2);
  391.           pcomp->proto = htons(PROTO_VJCOMP);
  392.           pcomp->slots = MAX_STATES - 1;
  393.           pcomp->compcid = 0;
  394.           bcopy(&pcomp, nakp + 2, sizeof(pcomp));
  395.           nakp += length;
  396.         }
  397.         break;
  398.       default:
  399.         bcopy(cp, rejp, length);
  400.         rejp += length;
  401.         break;
  402.       }
  403.     }
  404.     break;
  405.       case MODE_NAK:
  406.     LogPrintf(LOG_LCP, "%s changing compproto: %08x --> %08x\n",
  407.       tbuff, IpcpInfo.want_compproto, compproto);
  408.     IpcpInfo.want_compproto = compproto;
  409.     break;
  410.       case MODE_REJ:
  411.     IpcpInfo.his_reject |= (1 << type);
  412.     break;
  413.       }
  414.       break;
  415.     case TY_IPADDRS:    /* RFC1172 */
  416.       lp = (u_long *)(cp + 2);
  417.       ipaddr.s_addr = *lp;
  418.       lp = (u_long *)(cp + 6);
  419.       dstipaddr.s_addr = *lp;
  420.       LogPrintf(LOG_LCP, "%s %s, ", tbuff, inet_ntoa(ipaddr));
  421.       LogPrintf(LOG_LCP, "%s\n", inet_ntoa(dstipaddr));
  422.  
  423.       switch (mode) {
  424.       case MODE_REQ:
  425.     IpcpInfo.his_ipaddr = ipaddr;
  426.     IpcpInfo.want_ipaddr = dstipaddr;
  427.     bcopy(cp, ackp, length);
  428.     ackp += length;
  429.     break;
  430.       case MODE_NAK:
  431.     LogPrintf(LOG_LCP, "%s changing address: %s ",
  432.       tbuff, inet_ntoa(IpcpInfo.want_ipaddr));
  433.     LogPrintf(LOG_LCP, "--> %s\n", inet_ntoa(ipaddr));
  434.     IpcpInfo.want_ipaddr = ipaddr;
  435.     IpcpInfo.his_ipaddr = dstipaddr;
  436.     break;
  437.       case MODE_REJ:
  438.     IpcpInfo.his_reject |= (1 << type);
  439.     break;
  440.       }
  441.       break;
  442.     default:
  443.       IpcpInfo.my_reject |= (1 << type);
  444.       bcopy(cp, rejp, length);
  445.       rejp += length;
  446.       break;
  447.     }
  448.     plen -= length;
  449.     cp += length;
  450.   }
  451. }
  452.  
  453. void
  454. IpcpInput(struct mbuf *bp)
  455. {
  456.   FsmInput(&IpcpFsm, bp);
  457. }
  458.